const fs = require("fs");
const p = require("path");
const minimatch = require("minimatch");

const patternMatcher = (pattern) => {
	return (path, stats) => {
		const minimatcher = new minimatch.Minimatch(pattern, {matchBase: true});
		return (!minimatcher.negate || stats.isFile()) && minimatcher.match(path);
	};
};

const toMatcherFunction = (ignoreEntry) => {
	if (typeof ignoreEntry == "function") {
		return ignoreEntry;
	} else {
		return patternMatcher(ignoreEntry);
	}
};

const readdir = (path, ignores, callback) => {
	if (typeof ignores == "function") {
		callback = ignores;
		ignores = [];
	}
	ignores = ignores.map(toMatcherFunction);
	
	let list = [];
	
	fs.readdir(path, function (err, files) {
		if (err) {
			return callback(err);
		}
		
		let pending = files.length;
		if (!pending) {
			// we are done, woop woop
			return callback(null, list);
		}
		
		files.forEach(function (file) {
			const filePath = p.join(path, file);
			fs.stat(filePath, function (_err, stats) {
				// console.log(filePath);
				if (_err) {
					return callback(_err);
				}
				
				if (ignores.some(function (matcher) {
					return matcher(filePath, stats);
				})) {
					pending -= 1;
					if (!pending) {
						return callback(null, list);
					}
					return null;
				}
				
				if (stats.isDirectory()) {
					readdir(filePath, ignores, function (__err, res) {
						if (__err) {
							return callback(__err);
						}
						
						list = list.concat(res);
						pending -= 1;
						if (!pending) {
							return callback(null, list);
						}
					});
				} else {
					list.push(filePath);
					pending -= 1;
					if (!pending) {
						return callback(null, list);
					}
				}
				
			});
		});
	});
};

module.exports = readdir;